<template>
  <div class="home">
    <p>uname: {{ uname }}</p>
    <button @click="setUname">setUname</button>
    <p>user: {{ user }}</p>
    <button @click="setUser">setUser</button>
    <p>user: {{ user1 }}</p>
    <button @click="setUserOne">setUserOne</button>
    <p>arr: {{ arr }}</p>
    <button @click="setArr">setArr</button>
    <hr />
    <h3>子组件区域</h3>
    <to-ref :a="100" :b="200" m="1" n="2" @setdata="receiveData">
      <a href="#">插槽内容</a>
    </to-ref>
    <p>父组件接收传值：{{ sonData }}</p>
    <hr />
    <readonly></readonly>
    <hr />
    <computed></computed>
    <hr />
    <watch></watch>
  </div>
</template>

<script>
import { reactive, ref } from "vue";
import ToRef from "@/components/01-toRef_toRefs";
import Readonly from "@/components/02-readonly";
import Computed from "@/components/03-computed";
import Watch from "@/components/04-watch";
export default {
  name: "HomeView",
  components: {
    ToRef,
    Readonly,
    Computed,
    Watch,
  },
  setup() {
    // 1. setup 不能用async修饰，因为返回值变成了promise
    // 2. 该函数在beforeCreate之前执行, 执行时机更早

    // ref() => RefImpl: 声明基本数据类型的响应式数据.
    const uname = ref("小明");
    const setUname = () => {
      console.log(uname);
      uname.value = "小王"; // 修改ref响应式数据(RefImpl), 使用.value
    };
    const user = ref({
      name: "张三",
      age: 22,
    });
    const setUser = () => {
      console.log(user);
      user.value.name = "李四";
    };

    // ref(): 声明响应式数据, 一般用作基本数据类型的声明, 但是引用类型数组和对象也能使用, 但是不管是哪种类型的数据, 都必须使用.value修改数据. 对于对象/数组类型来说, 不是特别方便, 而是使用reactive()来声明引用类型的响应式数据.

    // reactive() => Proxy: 声明引用类型的响应式数据. 返回值是Proxy代理对象, 也是vue3中实现数据响应式的核心用法. 而vue2中实现数据响应式的是Object.defineProperty().
    const user1 = reactive({
      name: "王五",
    });
    const setUserOne = () => {
      console.log(user1); // Proxy
      // user1.name = "赵武";
      // user1.address = "郑州"; // 动态新增属性
      delete user1.name; // 动态删除属性
    };
    const arr = reactive([1, 2, 3]);
    const setArr = () => {
      console.log(arr); // Proxy
      arr.push(4, 5, 6);
    };

    let sonData = reactive({
      data: {},
    });
    console.log("1....", sonData);
    const receiveData = data => {
      console.log("接收: ", data);
      // sonData = data; // 修改了sonData 的指向，原来是一个Proxy对象，现在是普通的JS对象，数据的响应性丢失了
      // console.log("2....", sonData);
      sonData.data = data; // 保持了sonData的数据响应性
    };

    // 3. setup内部声明的数据和函数, 想在组件模板中使用, 一定记得return
    return {
      uname,
      setUname,
      user,
      setUser,
      user1,
      setUserOne,
      arr,
      setArr,
      receiveData,
      sonData,
    };
  },
};
</script>
